using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;

namespace PlainConcepts.Fx.Dnie.CertStore
{
    /// <summary>
    /// Simple class to manage de certificate store
    /// </summary>
    class CertStoreHelper
        :IDisposable
    {
        #region Members

        /// <summary>
        /// Certificate store
        /// </summary>
        X509Store store;

        #endregion

        #region Constructors

        /// <summary>
		/// Default constructor
		/// </summary>
		public CertStoreHelper()
		{
		}

		#endregion

		#region Public Methods

        /// <summary>
        /// Obtain DniIdentity reading Dni-e 
        /// </summary>
        /// <returns>Identity of Dni-e</returns>
        /// <see cref="PlainConcepts.Fx.DnieIdentity"/>
		public DnieIdentity GetDnieIdentity()
		{
			//Open certificate store, if smart card is present ping window show in top most

            OpenStore();

			//Find certificates in store with SimpleName equals AC DNIE

			X509Certificate2Collection certCollection = store.Certificates;
            string simpleName = default(string);

			foreach (X509Certificate2 cert in certCollection)
			{
				simpleName = cert.GetNameInfo(X509NameType.SimpleName, true);

				if (
                    simpleName.Contains(Resources.Strings.SimpleNameKey) 
                    && 
                    cert.Subject.Contains(Resources.Strings.CertSubjectAuthentication)
                    )
				{
					
                    //get data and return DnieIdentity
					DnieIdentity identity = ParseSubject(cert.Subject);
					store.Close();
					return identity;
				}
				else
					continue;
				
			}
			throw new InvalidOperationException(Resources.Messages.exception_CertStoreHelper_NoCertificatePresent);
		}
        /// <summary>
        /// Get Certificate to Sign Documents
        /// </summary>
        /// <returns>Dnie certificate to sign documents</returns>
        /// <see cref="System.Security.Cryptography.X509Certificates.X509Certificate2"/>
		public X509Certificate2 GetCertificateToSign()
		{
			//Open certificate store, if smart card is present ping window show in top most

            OpenStore();

			//Find certificates in store with SimpleName equals AC DNIE
			X509Certificate2Collection certCollection = store.Certificates;

			foreach (X509Certificate2 cert in certCollection)
			{
				string simpleName = cert.GetNameInfo(X509NameType.SimpleName, true);
				if (simpleName.Contains(Resources.Strings.SimpleNameKey))
				{
					if (cert.Subject.Contains(Resources.Strings.CertSubjectSign))
						return cert; // return X509 certificate
					else
						continue;
				}
			}
			throw new InvalidOperationException(Resources.Messages.exception_CertStoreHelper_NoCertificatePresent);
		}

		#endregion

		#region Private Methods

        /// <summary>
        /// Open Certificate Store
        /// </summary>
        private void OpenStore()
        {
            if (store == null)
            {
                store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
            }
        }
        /// <summary>
        /// Close Certificate Store
        /// </summary>
        private void CloseStore()
        {
            if (store != null)
                store.Close();
        }
        /// <summary>
        /// Get DnieIdentitiy
        /// </summary>
        /// <param name="subject">Certificate Subject to parse</param>
        /// <returns>DenieIdentity</returns>
        /// <see cref="PlainConcepts.Fx.DnieIdentity"/>
		private DnieIdentity ParseSubject(string subject)
		{
			string[] splitedValues = subject.Split(',');

			//get splited values, lastname, firstname and dni serialnumber

			string lastName = splitedValues[0].Replace(Resources.Strings.CertCN, "");
			string firstName = splitedValues[2].Replace(Resources.Strings.CertG, "").TrimStart();
			string dni = splitedValues[4].Replace(Resources.Strings.CertSerialNumber, "").TrimStart();

			return new DnieIdentity(lastName, firstName, dni);
		}

		#endregion

        #region IDisposable Members

        /// <summary>
        /// IDisposable.Dispose
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// Dispose class
        /// </summary>
        /// <param name="disposing">True to dispose managed resources</param>
        public void Dispose(bool disposing)
        {
            CloseStore();
        }
        /// <summary>
        /// Finalizer of CertStoreHelper
        /// </summary>
        ~CertStoreHelper()
        {
            Dispose(false);
        }

        #endregion
    }
}
